<?php
	require_once(dirname(__FILE__)."/../../debug.php");
	require_once(dirname(__FILE__)."/../common/zip/Gzip.php");
/*
 * WFHttpTalk makes HTTP communication very easy.
 */
/* Methods
// Basic HTTP Settings
public function setURL($iURL)
public function setAcceptEncoding($Encoding)
public function setProtocol_HTTP()
public function setProtocol_HTTPS()
public function setServer($iServer)
public function setPort($iPort)
public function setPath($iPath)
public function setCGI( $ikey, $ivalue)
public function setCGI_all($iCGI)
public function setRawData($data)
public function setCGI_POSTURL_ARG($iArg)
public function setMethod_GET() 
public function setMethod_POST()
public function setReferer($iReferer)
public function setAgent($iAgent)
public function setGzipAutoDecode($bSet)

// HTTP Auth Settings
public function setAuthInfo( $iUser, $iPass)
public function setAuthType_BASIC()
public function setAuthType_NTLM()
public function setAuthType_GSSNEG()
public function setAuthType_ANY()

// Proxy Settings
public function setProxyType_HTTP()
//public function setProxyType_SOCKS4()
public function setProxyType_SOCKS5()
public function setProxyServer($iServer)
public function setProxyPort($iPort)
public function setProxyAuthInfo( $iUser, $iPass)

// Timeout Settings
public function setTimeout($iSeconds)
public function setTimeout_connect($iSeconds)
public function setTimeout_dnscache($iSeconds)

// Request Header
public function setHeader( $iName, $iValue)
public function setHeaders($iHeaders)

// Cookie Settings
public function setCookies($iCookies)
public function setCookieStr($iCookieStr)

// make a talk with the http server
public function Send()

// get response header, return: array
public function getHeaders()
public function getHeaderField($iField)

// get response body
public function getBody()


// get response code
public function getCode()

// get response cookies
public function getCookies()
public function getCookieField($iField)
public function getCookieStr()

// get RAW response
public function getRawResponse()

// error handling
public function getErrMessage()
public function getErrCode()
*/
?>
<?php /* sample code here */
/*
$mylogin = new WFHttpTalk();
$mylogin->setServer("10.2.168.179");$mylogin->setProtocol_HTTPS();$mylogin->setPath("/index.php");$mylogin->setPort(4343);
//$mylogin->setTimeout(1);
//$mylogin->setTimeout_connect(1);
$mylogin->Send();
if($mylogin->getErrCode()===0)
{
	$tarray = $mylogin->getHeaders();
	echo "<h1>getHeaders</h1><BR>\n";
	print_r($tarray);

	echo "<h1>getCode</h1><BR>\n";
	echo $mylogin->getCode()."<BR>";

	echo "<h1>getCookies</h1><BR>\n";
	$tarray = $mylogin->getCookies();
	print_r($tarray);

	echo "<h1>Body</h1><BR>\n";
	echo $mylogin->getBody();

	$htmldom = new DOMDocument();
	$htmldom->loadHTML($mylogin->getBody());

	$pubkey = $htmldom->getElementById("pubkey")->getAttribute("value");
	$nonce = $htmldom->getElementById("nonce")->getAttribute("value");
	$sid = $htmldom->getElementById("sid")->getAttribute("value");
}
else
{
	echo "Failed error code:".$mylogin->getErrCode()."\n";
	echo "Failed reason:".$mylogin->getErrMessage()."\n";	
}
*/
?>
<?php

	class WFHttpTalk {
		// private --------------------------
		private $_objcurlHandle; //Curl Handle
		private $_mixcurlResponse; // Curl Response
		private $_arrcurlResponseHeader; //Curl Response Header
		private $_strcurlResponseBody; //Curl Response Body
		private $_intcurlResponseCode; //Curl Response Code
		private $_arrcurlResponseCookie; //Curl Response Cookie
		private $_boocurlAutoGZDecode=true;// Let HttpTalk to decode GZIP for you or not
		private $_booDataArray=false;
		

		/* Custom Request */
		private $_strCustomRequest = "";

		/* url information */
		private $_strurlProtocol = "http";
		private $_strurlServer = "";
		private $_inturlPort = 80;
		private $_strurlPath = "/";
		private $_arrurlCGI = array();

		/* error handling */
		private $_strerrMessage = "";
		private $_interrCode = 0;
		/* http method */
		private $_intmethod = CURLOPT_HTTPGET; // CURLOPT_POST, CURLOPT_NOBODY, ... (for now, we only support 3 methods)
		private $_boopost_with_urlencoded=false;
		private $_arrhttpOptions = array(
					CURLOPT_URL => "", // will be made before send()
					CURLOPT_REFERER => "",
					CURLOPT_USERAGENT => "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)"
					);

		private $_arrauthOptions = array(
					CURLOPT_USERPWD => "", // "user:pass"
					CURLOPT_HTTPAUTH => CURLAUTH_BASIC // CURLAUTH_DIGEST, CURLAUTH_GSSNEGOTIATE, CURLAUTH_NTLM, CURLAUTH_ANY, CURLAUTH_ANYSAFE
					);

		private $_arrproxyOptions = array(
					CURLOPT_PROXY => "",
					CURLOPT_PROXYPORT => 8080,
					CURLOPT_PROXYTYPE => CURLPROXY_HTTP , // CURLPROXY_SOCKS5
					CURLOPT_PROXYUSERPWD => "", // "user:pass"
					CURLOPT_PROXYAUTH => CURLAUTH_BASIC // CURLAUTH_DIGEST, CURLAUTH_GSSNEGOTIATE, CURLAUTH_NTLM, CURLAUTH_ANY, CURLAUTH_ANYSAFE
					);

		// public --------------------------
		public function __construct() {
			$this->_objcurlHandle=curl_init() or die(curl_error());
			curl_setopt($this->_objcurlHandle,CURLOPT_COOKIEFILE,"");
			curl_setopt($this->_objcurlHandle,CURLOPT_COOKIEJAR,"");
			curl_setopt($this->_objcurlHandle,CURLOPT_HTTPHEADER,array("Expect:","Accept-Encoding:gzip,deflate"));			
		}
		
		public function __destruct(){
			curl_close($this->_objcurlHandle);
		}
		
		public function setProtocol_HTTP() { $this->_strurlProtocol = "http"; }
		public function setProtocol_HTTPS() { $this->_strurlProtocol = "https"; }

		/* Basic HTTP Settings */
		public function setURL($striURL) { $this->_arrhttpOptions[CURLOPT_URL] = $striURL; }
		public function setServer($striServer) { $this->_strurlServer = $striServer; }
		public function	setPort($intiPort) { $this->_inturlPort = $intiPort; }
		public function setGzipAutoDecode($booAnswer) { $this->_boocurlAutoGZDecode = $booAnswer; }
		public function setPath($striPath) {
			if( $striPath[0] == '/' ) {
				$this->_strurlPath = $striPath;
			} else {
				$this->_strurlPath = "/".$striPath;
			}
			// clear $this->_arrhttpOptions["url"], then it will be rebuilt
			$this->_arrhttpOptions[CURLOPT_URL] = "";
			//reset URL parameters
			unset($this->_arrurlCGI);
			$this->_arrurlCGI=array();
		}
		public function setCGI( $strikey, $strivalue) { $this->_arrurlCGI["$strikey"] = $strivalue; }
		public function setCGI_all($arriCGI) { $this->_arrurlCGI = $arriCGI; }
		
		// set POST raw data
		public function setRawData($data) {
			if(is_array($data)) { $this->_booDataArray = true; }
			else { $this->_booDataArray = false; }
			curl_setopt ( $this->_objcurlHandle, CURLOPT_POSTFIELDS, $data);
		}
		
		public function	setMethod_GET() { $this->_intmethod = CURLOPT_HTTPGET; }
		public function	setMethod_POST($_boopost_with_urlencoded=false) { $this->_intmethod = CURLOPT_POST; $this->_boopost_with_urlencoded=$_boopost_with_urlencoded;}
		public function setReferer($striReferer) { $this->_arrhttpOptions[CURLOPT_REFERER] = $striReferer; }
		public function setAgent($striAgent) { $this->_arrhttpOptions[CURLOPT_USERAGENT] = $striAgent; }

		/* HTTP Auth Settings */
		public function setAuthInfo( $iUser, $iPass) { $this->_arrauthOptions[CURLOPT_USERPWD] = $iUser.":".$iPass; }
		public function setAuthType_BASIC() { $this->_arrauthOptions[CURLOPT_HTTPAUTH] = CURLAUTH_BASIC; }
		public function setAuthType_NTLM() { $this->_arrauthOptions[CURLOPT_HTTPAUTH] = CURLAUTH_NTLM; }
		public function setAuthType_GSSNEG() { $this->_arrauthOptions[CURLOPT_HTTPAUTH] = CURLAUTH_GSSNEGOTIATE; }
		public function setAuthType_ANY() { $this->_arrauthOptions[CURLOPT_HTTPAUTH] = CURLAUTH_ANY; }

		/* Proxy Settings */
		public function setProxyType_HTTP() { $this->_arrproxyOptions[CURLOPT_PROXYTYPE] = CURLPROXY_HTTP; }
		/*public function setProxyType_SOCKS4() { $this->_arrproxyOptions[CURLOPT_PROXYTYPE] = CURLPROXY_SOCKS4; }*/
		public function setProxyType_SOCKS5() { $this->_arrproxyOptions[CURLOPT_PROXYTYPE] = CURLPROXY_SOCKS5; }
		public function setProxyServer($striServer) { $this->_arrproxyOptions[CURLOPT_PROXY] = $striServer; }
		public function setProxyPort($intiPort) { $this->_arrproxyOptions[CURLOPT_PROXYPORT] = $intiPort; }
		public function setProxyAuthInfo( $striUser, $striPass) { $this->_arrproxyOptions[CURLOPT_PROXYUSERPWD] = $striUser.":".$striPass; }

		public function SetCustomRequest($strRequestInfo) { $this->_strCustomRequest = $strRequestInfo;}

		/* Timeout Settings */
		public function setTimeout($intiSeconds) { $this->_arrhttpOptions[CURLOPT_TIMEOUT] = $intiSeconds; }
		public function setTimeout_connect($intiSeconds) { $this->_arrhttpOptions[CURLOPT_CONNECTTIMEOUT] = $intiSeconds; }
		public function setTimeout_dnscache($intiSeconds) { $this->_arrhttpOptions[CURLOPT_DNS_CACHE_TIMEOUT] = $intiSeconds; }

		/* Request Header */
		public function setHeader( $striName, $striValue) {
			//mydebug_log("setHeader");
			//mydebug_log("$striName, $striValue");
			$arrnheader = array();
			$arrnheader[$striName] = $striValue;
			curl_setopt($this->_objcurlHandle,CURLOPT_HTTPHEADER,$arrnheader);
		}
		public function setHeaders($arriHeaders) { curl_setopt($this->_objcurlHandle,CURLOPT_HTTPHEADER,$arriHeaders); }
		
		/* Cookie Settings */
		public function setCookies($arriCookies) {
			$strcookie_str = "";
			if (is_array ( $arriCookies )) {
				foreach ( $arriCookies as $strckkey => $strckvalue ) {
					if ($strcookie_str == "") {
						$strcookie_str = $strckkey . "=" . $strckvalue;
					} else {
						$strcookie_str = $strcookie_str . "; " . $strckkey . "=" . $strckvalue;
					}
				}
			}
			curl_setopt ( $this->_objcurlHandle, CURLOPT_COOKIE, $strcookie_str );
		}
		public function setCookieStr($striCookieStr) {
			curl_setopt($this->_objcurlHandle,CURLOPT_COOKIE,$striCookieStr);
		}

		/*
		 * Sent()
		 * Input: void
		 * Return: TRUE or FALSE
		 * Description:
		 *	- send request
		 *	- set $this->_strerrMessage when failed
		 */
		public function	Send() {
			$this->resetErrorInfo();
			/* set method */
			if(!$this->_booDataArray)
			{
				if($this->_intmethod == CURLOPT_POST)
					curl_setopt($this->_objcurlHandle,CURLOPT_POST,true);
				else if($this->_intmethod ==CURLOPT_HTTPGET)
					curl_setopt($this->_objcurlHandle,CURLOPT_HTTPGET,true);
				else
					curl_setopt($this->_objcurlHandle,CURLOPT_NOBODY,true);
			}
			
			if( $this->_arrhttpOptions[CURLOPT_URL] == "" )
			{
				$strurl = "";
				/* make URL and cgi string */
				if( $this->_intmethod ==  CURLOPT_HTTPGET) {
					$strurlCGIstr = "";
					/* cgi str */
					if (is_array ($this->_arrurlCGI)) {
						foreach ( $this->_arrurlCGI as $strcgikey => $strcgivalue ) {
							$strurlCGIstr = $strurlCGIstr . $strcgikey . "=" . $strcgivalue;
						}
					}
					if( count($this->_arrurlCGI) > 0 ) {
						$strurl = $this->_strurlProtocol."://".$this->_strurlServer.":".$this->_inturlPort.$this->_strurlPath."?".$strurlCGIstr;
					} else {
						$strurl = $this->_strurlProtocol."://".$this->_strurlServer.":".$this->_inturlPort.$this->_strurlPath;
					}
				} else if( $this->_intmethod == CURLOPT_POST ) {
					$strurl = $this->_strurlProtocol."://".$this->_strurlServer.":".$this->_inturlPort.$this->_strurlPath;
					if($this->_boopost_with_urlencoded)
					{
						$strtemp="";
						if (is_array ( $this->_arrurlCGI )) {
							foreach ( $this->_arrurlCGI as $strcgikey => $strcgivalue ) {
								$strtemp = $strtemp . $strcgikey . "=" . $strcgivalue . "&";
							}
						}
						curl_setopt($this->_objcurlHandle,CURLOPT_POSTFIELDS,$strtemp);
					}
					else
						curl_setopt($this->_objcurlHandle,CURLOPT_POSTFIELDS,$this->_arrurlCGI);
				}
				/* set URL */
				$this->_arrhttpOptions[CURLOPT_URL] = $strurl;
			}
			else if($this->_intmethod == CURLOPT_POST && $this->_arrhttpOptions[CURLOPT_URL] != ""  && count($this->_arrurlCGI) > 0)
			{
					if($this->_boopost_with_urlencoded)
					{
						$strtemp="";
						if (is_array ( $this->_arrurlCGI )) {
							foreach ( $this->_arrurlCGI as $strcgikey => $strcgivalue ) {
								$strtemp = $strtemp . $strcgikey . "=" . $strcgivalue . "&";
							}
						}
						curl_setopt($this->_objcurlHandle,CURLOPT_POSTFIELDS,$strtemp);
					}
					else
						curl_setopt($this->_objcurlHandle,CURLOPT_POSTFIELDS,$this->_arrurlCGI);
			}
				
			curl_setopt_array($this->_objcurlHandle, $this->_arrhttpOptions);
			
			if( $this->_arrauthOptions[CURLOPT_USERPWD] !== "" ) {
				curl_setopt_array($this->_objcurlHandle, $this->_arrauthOptions);
			}
			if( $this->_arrproxyOptions[CURLOPT_PROXY] !== "" ) {
				curl_setopt_array($this->_objcurlHandle, $this->_arrproxyOptions);
			}
			curl_setopt($this->_objcurlHandle, CURLOPT_FOLLOWLOCATION,false);
			curl_setopt($this->_objcurlHandle, CURLOPT_RETURNTRANSFER,true);
			curl_setopt($this->_objcurlHandle, CURLOPT_HEADER, true);
			curl_setopt($this->_objcurlHandle, CURLOPT_SSL_VERIFYHOST, 0);
			curl_setopt($this->_objcurlHandle, CURLOPT_SSL_VERIFYPEER, 0); 				
			 
			if($this->_strCustomRequest != ""){
				curl_setopt($this->_objcurlHandle, CURLOPT_CUSTOMREQUEST, $this->_strCustomRequest);
				//reset $this->_strCustomRequest
				$this->_strCustomRequest = "";
			}

			// do send
			try {
				$this->_mixcurlResponse=false;
				$this->_mixcurlResponse=curl_exec($this->_objcurlHandle);
				
				//mydebug_log("HEADER BEGIN");
				$tmpary = curl_getinfo($this->_objcurlHandle);
				
				//foreach ($tmpary as $tmpkey => $tmpvalue){
				//	mydebug_log("$tmpkey => $tmpvalue");
				//}
				//mydebug_log("HEADER END");
				
				if($this->_mixcurlResponse === false)
				{
					$this->_interrCode=curl_errno($this->_objcurlHandle);
					//mydebug_log("[HTTPTALK]Failed error code:".$this->_interrCode);
					$this->_strerrMessage=curl_error($this->_objcurlHandle);
					//mydebug_log("[HTTPTALK]Failed reason:".$this->_strerrMessage);
					return FALSE;
				}
				$strResponseHeaderString="";
				$this->_strcurlResponseBody="";
				if(preg_match("/Proxy-agent:/i",$this->_mixcurlResponse))
				{
					$intproxyagentpos=strpos($this->_mixcurlResponse, "Proxy-agent:");
					$intpos = strpos($this->_mixcurlResponse, "\r\n\r\n");
					if($intproxyagentpos < $intpos)
						$this->_mixcurlResponse=substr($this->_mixcurlResponse,$intpos+4);
				}
				
				// patch for IDF : 100 Continue
				if (preg_match('/HTTP\/1.1 100 Continue/i', $this->_mixcurlResponse))
				{
					$int100pos = strpos($this->_mixcurlResponse, '/HTTP/1.1 100 Continue');
					$intpos = strpos($this->_mixcurlResponse, "\r\n\r\n");
					if ($int100pos < $intpos) 
                        $this->_mixcurlResponse = substr($this->_mixcurlResponse, $intpos+4);
				}

				list($strResponseHeaderString,$this->_strcurlResponseBody) = explode("\r\n\r\n", $this->_mixcurlResponse,2);
			
				$this->_intcurlResponseCode = curl_getinfo($this->_objcurlHandle,CURLINFO_HTTP_CODE);
        		$this->_arrcurlResponseHeader = $this->curlHttpParseHeaders($strResponseHeaderString);
        		$this->_arrcurlResponseCookie=array();
        		preg_match_all('/Set-Cookie: ([^=]+)=(.*?);/i', $strResponseHeaderString, $arrmatches);
				if (is_array ( $arrmatches [1] )) {
					foreach ( $arrmatches [1] as $strkey => $strval ) {
						$this->_arrcurlResponseCookie [( string ) $strval] = $arrmatches [2] [$strkey];
					} // foreach
				} 
			} catch (Exception $ex) {
				$this->_interrCode = -1;
				$this->_strerrMessage = $ex->getMessage();
				mydebug_log("[HTTPTALK]Got exception:".$this->_strerrMessage);
				return FALSE;
			}
			return TRUE;
		}
			
		
		/*
		 * 'get' functions
		 */
		/* get response header */ /* return: array */
		public function getHeaders() { return $this->_arrcurlResponseHeader; }
		public function getHeaderField($mixiField) { /* mixiField: mixed, could be string or array.` */
			$arrheaders = $this->_arrcurlResponseHeader;
			if( isset($arrheaders["$mixiField"]) ) {
				return $arrheaders["$mixiField"];
			}
			return NULL;
		}
		/* get response body */ /* return: string */
		public function getBody() {
			if ($this->_boocurlAutoGZDecode && isset($this->_arrcurlResponseHeader["Content-Encoding"]) && $this->_arrcurlResponseHeader["Content-Encoding"]==="gzip")
			{
				return WFGzip::gzdecode($this->_strcurlResponseBody);
			}
			else
			{
				return $this->_strcurlResponseBody;
			}
		}
		/* get response code */ /* return: int */
		public function getCode() { return $this->_intcurlResponseCode; }
		/* get response cookies */ /* return: array */
		public function getCookies() { return $this->_arrcurlResponseCookie; }
			
		public function getCookieField($mixiField) {
			$arrcookies = $this->getCookies();
			if( isset($arrcookies["$mixiField"])) {
				return $arrcookies["$mixiField"];
			}
			return NULL;
		}
		public function getCookieStr() {
			$arrcookies = $this->getCookies();
			$strcookie_str = "";
			if (is_array ( $arrcookies )) {
				foreach ( $arrcookies as $strckkey => $strckvalue ) {
					if ($strcookie_str == "") {
						$strcookie_str = $strckkey . "=" . $strckvalue;
					} else {
						$strcookie_str = $strcookie_str . "; " . $strckkey . "=" . $strckvalue;
					}
				}
			}
			return $strcookie_str;
		}
		public function getRawResponse() { return $this->_mixcurlResponse; }
		public function getErrMessage() { return $this->_strerrMessage; }
		public function getErrCode() { return $this->_interrCode; }
		private function resetErrorInfo(){
			$this->_strerrMessage="";
			$this->_interrCode=0;
		}
        private function curlHttpParseHeaders( $strheader )
        {
            $arrretVal = array();
            $arrfields = explode("\r\n", preg_replace('/\x0D\x0A[\x09\x20]+/', ' ', $strheader));
            foreach( $arrfields as $strfield ) {
                if( preg_match('/([^:]+): (.+)/m', $strfield, $arrmatch) ) {
                    $arrmatch[1] = preg_replace('/(?<=^|[\x09\x20\x2D])./e', 'strtoupper("\0")', strtolower(trim($arrmatch[1])));
                    if( isset($arrretVal[$arrmatch[1]]) ) {
                        if (is_array($arrretVal[$arrmatch[1]]))
                        {
                            array_push($arrretVal[$arrmatch[1]], $arrmatch[2]);
                        }
                        else
                        {
                            $arrretVal[$arrmatch[1]] = array($arrretVal[$arrmatch[1]], $arrmatch[2]);
                        }
                    } else {
                        $arrretVal[$arrmatch[1]] = trim($arrmatch[2]);
                    }
                }
            }
            return $arrretVal;
        }
	};
